﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ImageProcessor;
using ImageProcessor.Imaging;
//794*1123
namespace ConsoleApp1
{
    class Program
    {
        [STAThread]
//        public static int width = 1200;
        static void Main(string[] args)
        {

//            图片垂直合并("C:\\Users\\ACER\\Desktop\\repos\\524", "C:\\Users\\ACER\\Desktop\\repos\\524fix", 1123);
//            颜色替换目录("C:\\Users\\ACER\\Desktop\\repos\\524fix",Color.FromArgb(255, 166, 166), Color.White, 84);
//            颜色替换目录("C:\\Users\\ACER\\Desktop\\repos\\524fix",Color.FromArgb(0, 0, 255), Color.Black, 84);
//            颜色替换目录("C:\\Users\\ACER\\Desktop\\repos\\524fix", Color.FromArgb(0x83, 0x8f, 0x3e), Color.Black, 124);
//            颜色替换目录二("C:\\Users\\ACER\\Desktop\\repos\\524fix");
            var sim = Image.FromFile("C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp");

            string[] files = Directory.GetFiles("C:\\Users\\ACER\\Desktop\\repos\\524fix");
            Directory.CreateDirectory("C:\\Users\\ACER\\Desktop\\repos\\524fix-44");
            Parallel.ForEach(files, new ParallelOptions() {MaxDegreeOfParallelism = 3}, (file =>
            {
                var a = FindPicture("C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp",
                    file, Rectangle.Empty, 40, 0.9, true);
                var bp = Image.FromFile(file);
                Graphics g = Graphics.FromImage(bp);
                foreach (Point point in a)
                {
                    g.FillRectangle(Brushes.White, point.X - sim.Width / 2, point.Y - sim.Height / 2, sim.Width,
                        sim.Height);


                }
                bp.Save(Path.Combine("C:\\Users\\ACER\\Desktop\\repos\\524fix-44", Path.GetFileName(file)));

                Console.WriteLine(file);
            }));

 


        }
        public static Bitmap ToGray(Bitmap bmp)
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    //获取该点的像素的RGB的颜色
                    Color color = bmp.GetPixel(i, j);
                    //利用公式计算灰度值
                    int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
                    Color newColor = Color.FromArgb(gray, gray, gray);
                    bmp.SetPixel(i, j, newColor);
                }
            }
            return bmp;
        }
        public static Bitmap ConvertTo1Bpp1(Bitmap bmp)
        {
            int average = 0;
            average = 20;

            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    //获取该点的像素的RGB的颜色
                    Color color = bmp.GetPixel(i, j);
                    int value = 255 - color.B;
                    Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255,

                        255, 255);
                    bmp.SetPixel(i, j, newColor);
                }
            }
            return bmp;
        }


        public static void 图片替换(string simpic,string fatherpic,string outputpic)
        {
            string[] files = Directory.GetFiles(fatherpic);
            Directory.CreateDirectory(outputpic);
            Bitmap sim = new Bitmap(simpic);
            for (int index = 0; index < files.Length; index++)
            {
                var bp = new Bitmap(files[index]);
                List<Point> list = BmpColor.FindPic(0, 0, bp.Width, bp.Height, bp, sim, 90);
                if (list.Count > 0)
                {
                    Graphics g = Graphics.FromImage(bp);
                    for (int i = 0; i < list.Count; i++)
                    {
                        g.FillRectangle(Brushes.White, list[i].X, list[i].Y, sim.Width, sim.Height);
                    }
                }
                bp.Save(Path.Combine(outputpic, Path.GetFileName(files[index])));

            }


        }
        public static void 图片替换s(string[] simpic, string fatherpic, string outputpic)
        {
            string[] files = Directory.GetFiles(fatherpic);
            Directory.CreateDirectory(outputpic);
            List<Bitmap> sims=new List<Bitmap>();
            foreach (string s in simpic)
            {
                sims.Add(new Bitmap(s));
            }
           
            for (int index = 0; index < files.Length; index++)
            {
                var bp = new Bitmap(files[index]);
                foreach (Bitmap sim in sims)
                {
                    List<Point> list = BmpColor.FindPic(0, 0, bp.Width, bp.Height, bp, sim, 40);
                    if (list.Count > 0)
                    {
                        Graphics g = Graphics.FromImage(bp);
                        for (int i = 0; i < list.Count; i++)
                        {
                            g.FillRectangle(Brushes.White, list[i].X, list[i].Y, sim.Width, sim.Height);
                        }
                    }
                }
               
                bp.Save(Path.Combine(outputpic, Path.GetFileName(files[index])));
                Console.WriteLine(files[index]);
            }


        }



        public static Bitmap Format24(string input)
        {
            var bmp = new Bitmap(input);

            Bitmap bitmap24 = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(bitmap24);
            g.DrawImageUnscaled(bmp, 0, 0);
            bmp.Dispose();
            g.Dispose();
            return bitmap24;
        }

       // 颜色替换
        public static void 颜色替换(string input, Color oldcolor, Color newcolor, int 容差)
        {

            Bitmap bmp = (Bitmap) Image.FromFile(input);
            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                    Color picker = bmp.GetPixel(j, i);
                    if (Math.Abs(picker.R - oldcolor.R) < 容差 && Math.Abs(picker.G - oldcolor.G) < 容差 &&
                        Math.Abs(picker.B - oldcolor.B) < 容差)
                    {
                        picker = newcolor;
                        bmp.SetPixel(j, i, picker);
                    }
// 
//                    if (picker.R < 150 && picker.G < 150 && picker.B < 150)
//                    {
//                        bmp.SetPixel(j, i, Color.Black);
//                    }
//                    else
//                    {
//                        bmp.SetPixel(j, i, Color.White);
//
//                    }
                }
            }

            var by = Bitmap2Byte(bmp);
            bmp.Dispose();
            File.WriteAllBytes(input, by);
        }

        public static void 颜色二(string input)
        {

            Bitmap bmp = (Bitmap)Image.FromFile(input);
            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                    Color picker = bmp.GetPixel(j, i);

                    if (picker.R < 150 && picker.G < 150 && picker.B < 150)
                    {
                        bmp.SetPixel(j, i, Color.Black);
                    }
                    else
                    {
                        bmp.SetPixel(j, i, Color.White);

                    }
                }
            }

            var by = Bitmap2Byte(bmp);
            bmp.Dispose();
            File.WriteAllBytes(input, by);
        }

        public static byte[] Bitmap2Byte(Image bitmap)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, ImageFormat.Jpeg);
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }
        public static void 颜色替换目录二(string input)
        {
            string[] files = Directory.GetFiles(input);
            if (files.Length == 0)
            {
                return;
            }
            Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = 4 }, s =>
            {
                颜色二(s);
                Console.WriteLine(s);
            });




        }
        public static void 颜色替换目录(string input, Color oldcolor, Color newcolor, int 容差)
        {
            string[] files = Directory.GetFiles(input);
            if (files.Length == 0)
            {
                return;
            }
            Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = 4 }, s =>
            {
                颜色替换(s, oldcolor, newcolor, 容差);
                Console.WriteLine(s);
            });




        }
        private static void 图片垂直合并(string inputdir,string outputdir,int height,int maxwidth=-1)
        {
            Directory.CreateDirectory(outputdir);

            int maxWidth = 0;
            string[] files = Directory.GetFiles(inputdir);
            if (files.Length==0)
            {
                return;
            }
            #region Maxwidth

            if (maxwidth <= 0)
            {
                foreach (string file in files)
                {
                    Image img = Image.FromFile(file);
                    maxWidth = maxWidth > img.Height ? maxWidth : img.Height;
                    img.Dispose();
                }
            }
            else
            {
                maxWidth = maxwidth;
            }

            #endregion

            Bitmap firstBitmap = (Bitmap)Image.FromFile(files[0]);
            
            int index = 0;
            for (var i = 1; i < files.Length; i++)
            {
                
                string file = files[i];
                Bitmap secondBitmap = (Bitmap)Image.FromFile(file);
                if (firstBitmap.Height + secondBitmap.Height > 1124)
                {
                    firstBitmap.Save(Path.Combine(outputdir, index.ToString("D5")+".png"),ImageFormat.Png);
                    index++;
                    firstBitmap = (Bitmap)Image.FromFile(files[i]);
                    continue;
                }
                firstBitmap = MergeImageVertical(firstBitmap, secondBitmap);
                secondBitmap.Dispose();
                Console.WriteLine(file);
            }
            firstBitmap.Save(Path.Combine(outputdir, index.ToString("D5") + ".png"), ImageFormat.Png);
            firstBitmap.Dispose();
        }
        private static void Resize(string[] files)
        {
            ImageProcessor.ImageFactory fac = new ImageFactory();

            foreach (string file in files)
            {
                var img = fac.Load(file);
                img.BackgroundColor(Color.White);
                var h = img.Image.Height;
                img.Resize(new ResizeLayer(new Size(930, h), ResizeMode.Pad, AnchorPosition.Left));
                img.Save(file);
                Console.WriteLine(file);
            }

        }
        //图片垂直合并
        private static Bitmap MergeImageVertical(Bitmap firstMap, Bitmap secondMap)
        {
            Bitmap newMap = null;
            int firstW, firstH, secondW, secondH;
            firstW = firstMap.Width;
            firstH = firstMap.Height;
            secondW = secondMap.Width;
            secondH = secondMap.Height;

            BitmapData firstBD =
            firstMap.LockBits(new Rectangle(0, 0, firstW, firstH),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData secondBD =
            secondMap.LockBits(new Rectangle(0, 0, secondW, secondH),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int firstStride = firstBD.Stride;
            int secondStride = secondBD.Stride;
            System.IntPtr firstScan0 = firstBD.Scan0;
            System.IntPtr secondScan0 = secondBD.Scan0;

            int maxW = firstW;
            if (maxW < secondW)
                maxW = secondW;
            newMap = new Bitmap(maxW, firstH + secondH);
            Graphics g1 = Graphics.FromImage(newMap);  //创建b1的Graphics
            g1.FillRectangle(Brushes.White, new Rectangle(0, 0, maxW, firstH + secondH));
            BitmapData newBD =
            newMap.LockBits(new Rectangle(0, 0, maxW, firstH + secondH),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            System.IntPtr newScan0 = newBD.Scan0;
            unsafe
            {
                int newMapStride = newBD.Stride;
                byte* pFirst = (byte*)(void*)firstScan0;
                byte* pSecond = (byte*)(void*)secondScan0;
                byte* pNew = (byte*)(void*)newScan0;
                int x, y, temp3W, tempYStride, tempYNewMapStride;
                byte temp1;
                //写入上边图像
                temp3W = 3 * firstW;
                for (y = 0; y < firstH; y++)
                {
                    tempYStride = y * firstStride;
                    tempYNewMapStride = y * newMapStride;
                    for (x = 0; x < temp3W; x++)
                    {
                        temp1 = pFirst[x + tempYStride];
                        pNew[x + tempYNewMapStride] = temp1;
                    }
                }

                //写入下边图像
                temp3W = 3 * secondW;
                for (y = 0; y < secondH; y++)
                {
                    tempYStride = y * secondStride;
                    tempYNewMapStride = (y + firstH) * (newMapStride);
                    for (x = 0; x < temp3W; x++)
                    {
                        temp1 = pSecond[x + tempYStride];
                        pNew[x + tempYNewMapStride] = temp1;
                    }
                }
                newMap.UnlockBits(newBD);
            }

            firstMap.UnlockBits(firstBD);
            secondMap.UnlockBits(secondBD);

            return newMap;
        }

        #region 找图

        /// <summary>
        /// 查找图片，不能镂空
        /// </summary>
        /// <param name="subPic"></param>
        /// <param name="parPic"></param>
        /// <param name="searchRect">如果为empty，则默认查找整个图像</param>
        /// <param name="errorRange">容错，单个色值范围内视为正确0~255</param>
        /// <param name="matchRate">图片匹配度，默认90%</param>
        /// <param name="isFindAll">是否查找所有相似的图片</param>
        /// <returns>返回查找到的图片的中心点坐标</returns>
      static  List<System.Drawing.Point> FindPicture(string subPic, string parPic, System.Drawing.Rectangle searchRect, byte errorRange, double matchRate = 0.9, bool isFindAll = false)
        {
            List<System.Drawing.Point> ListPoint = new List<System.Drawing.Point>();
            var subBitmap = new Bitmap(subPic);
            var parBitmap = new Bitmap(parPic);
            int subWidth = subBitmap.Width;
            int subHeight = subBitmap.Height;
            int parWidth = parBitmap.Width;
            int parHeight = parBitmap.Height;
            if (searchRect.IsEmpty)
            {
                searchRect = new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height);
            }

            var searchLeftTop = searchRect.Location;
            var searchSize = searchRect.Size;
            System.Drawing.Color startPixelColor = subBitmap.GetPixel(0, 0);
            var subData = subBitmap.LockBits(new System.Drawing.Rectangle(0, 0, subBitmap.Width, subBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var parData = parBitmap.LockBits(new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var byteArrarySub = new byte[subData.Stride * subData.Height];
            var byteArraryPar = new byte[parData.Stride * parData.Height];
            Marshal.Copy(subData.Scan0, byteArrarySub, 0, subData.Stride * subData.Height);
            Marshal.Copy(parData.Scan0, byteArraryPar, 0, parData.Stride * parData.Height);

            var iMax = searchLeftTop.Y + searchSize.Height - subData.Height;//行
            var jMax = searchLeftTop.X + searchSize.Width - subData.Width;//列

            int smallOffsetX = 0, smallOffsetY = 0;
            int smallStartX = 0, smallStartY = 0;
            int pointX = -1; int pointY = -1;
            for (int i = searchLeftTop.Y; i < iMax; i++)
            {
                for (int j = searchLeftTop.X; j < jMax; j++)
                {
                    //大图x，y坐标处的颜色值
                    int x = j, y = i;
                    int parIndex = i * parWidth * 4 + j * 4;
                    var colorBig = System.Drawing.Color.FromArgb(byteArraryPar[parIndex + 3], byteArraryPar[parIndex + 2], byteArraryPar[parIndex + 1], byteArraryPar[parIndex]);
                    ;
                    if (ColorAEqualColorB(colorBig, startPixelColor, errorRange))
                    {
                        smallStartX = x - smallOffsetX;//待找的图X坐标
                        smallStartY = y - smallOffsetY;//待找的图Y坐标
                        int sum = 0;//所有需要比对的有效点
                        int matchNum = 0;//成功匹配的点
                        for (int m = 0; m < subHeight; m++)
                        {
                            for (int n = 0; n < subWidth; n++)
                            {
                                int x1 = n, y1 = m;
                                int subIndex = m * subWidth * 4 + n * 4;
                                var color = System.Drawing.Color.FromArgb(byteArrarySub[subIndex + 3], byteArrarySub[subIndex + 2], byteArrarySub[subIndex + 1], byteArrarySub[subIndex]);

                                sum++;
                                int x2 = smallStartX + x1, y2 = smallStartY + y1;
                                int parReleativeIndex = y2 * parWidth * 4 + x2 * 4;//比对大图对应的像素点的颜色
                                var colorPixel = System.Drawing.Color.FromArgb(byteArraryPar[parReleativeIndex + 3], byteArraryPar[parReleativeIndex + 2], byteArraryPar[parReleativeIndex + 1], byteArraryPar[parReleativeIndex]);
                                if (ColorAEqualColorB(colorPixel, color, errorRange))
                                {
                                    matchNum++;
                                }
                            }
                        }
                        if ((double)matchNum / sum >= matchRate)
                        {
                            Console.WriteLine((double)matchNum / sum);
                            pointX = smallStartX + (int)(subWidth / 2.0);
                            pointY = smallStartY + (int)(subHeight / 2.0);
                            var point = new System.Drawing.Point(pointX, pointY);
                            if (!ListContainsPoint(ListPoint, point, 10))
                            {
                                ListPoint.Add(point);
                            }
                            if (!isFindAll)
                            {
                                goto FIND_END;
                            }
                        }
                    }
                    //小图x1,y1坐标处的颜色值
                }
            }
            FIND_END:
            subBitmap.UnlockBits(subData);
            parBitmap.UnlockBits(parData);
            subBitmap.Dispose();
            parBitmap.Dispose();
            GC.Collect();
            return ListPoint;
        }
        #endregion
        static bool ListContainsPoint(List<System.Drawing.Point> listPoint, System.Drawing.Point point, double errorRange = 10)
        {
            bool isExist = false;
            foreach (var item in listPoint)
            {
                if (item.X <= point.X + errorRange && item.X >= point.X - errorRange && item.Y <= point.Y + errorRange && item.Y >= point.Y - errorRange)
                {
                    isExist = true;
                }
            }
            return isExist;
        }
        static bool ColorAEqualColorB(System.Drawing.Color colorA, System.Drawing.Color colorB, byte errorRange = 10)
        {
            return colorA.A <= colorB.A + errorRange && colorA.A >= colorB.A - errorRange &&
                   colorA.R <= colorB.R + errorRange && colorA.R >= colorB.R - errorRange &&
                   colorA.G <= colorB.G + errorRange && colorA.G >= colorB.G - errorRange &&
                   colorA.B <= colorB.B + errorRange && colorA.B >= colorB.B - errorRange;

        }
    }
}
